package targaman.moltenwow.autovoter.gui;

import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.scene.Cursor;
import javafx.scene.control.*;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Ellipse;
import javafx.scene.text.Text;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import targaman.moltenwow.autovoter.Logger.MoltenLogger;
import targaman.moltenwow.autovoter.components.MoltenWoWLoginImpl;
import targaman.moltenwow.autovoter.controllers.ConfigurationImpl;
import targaman.moltenwow.autovoter.controllers.ConnectivityController;
import targaman.moltenwow.autovoter.lang.Constants;

import javax.swing.*;

@Service(value = Constants.GUI_CONTROLLER)
public class Controller {
    //TODO refactor variables to interface class? or abstract
    @FXML
    private TextField loginUsernameBox;

    @FXML
    private PasswordField loginPasswordBox;

    @FXML
    private Ellipse checkInternetConnectivityIndicator;

    @FXML
    private Ellipse checkMoltenConnectivityIndicator;

    @FXML
    private Ellipse loggedInIndicator;

    @FXML
    private CheckBox autovote, autologin;

    //Buttons
    @FXML
    private Button checkMoltenConnectivityButton, checkInternetConnectivityButton, loginButton, loggedInButton, votebutton1, votebutton2;

    @FXML
    private AnchorPane mainFrame;

    @FXML
    private ProgressBar loginProgress;

    @FXML
    private Text consoleLabel;

    @FXML
    private javafx.scene.control.TextArea console;

    @Autowired
    @Qualifier(value = Constants.CONNECTIVITY_CONTROLLER)
    private ConnectivityController connectivityControllerX;


    @Autowired
    @Qualifier(value = Constants.CONFIGURATION_SERVICE)
    private ConfigurationImpl configurationService;

    public static MoltenWoWLoginImpl http;

    Paint untested = Paint.valueOf("#ddd9d8");
    Paint failed = Paint.valueOf("#ff0000");
    Paint passed = Paint.valueOf("#21ff37");

    @FXML
    protected void voteSite1() {
        MoltenLogger.Log("Attempting Vote Site #1");
        boolean result = connectivityControllerX.vote(http.getConn(), 1);
        Platform.runLater(() -> votebutton1.setDisable(true));
    }

    @FXML
    protected void onAutoLoginClick() {
        if (loginUsernameBox.getText().length() > 1 && loginPasswordBox.getText().length() > 1) {
            configurationService.setAutoLogin(autologin.isSelected());
            configurationService.setDefaultLogin(loginUsernameBox.getText(), loginPasswordBox.getText()); //TODO Encrypt
            updateMenuGui();
            login();
        } else {
            autologin.setSelected(false);
            JOptionPane.showMessageDialog(null, "Please Enter a valid Username and Pasword!", "Auto Vote Selected!", JOptionPane.ERROR_MESSAGE);
        }
    }

    @FXML
    protected void onAutovoteClick() {
        configurationService.setAutoVote(autovote.isSelected());
        updateMenuGui();
    }

    @FXML
    protected void voteSite2() {
        MoltenLogger.Log("Attempting Vote Site #2");
        boolean result = connectivityControllerX.vote(http.getConn(), 2);
        Platform.runLater(() -> votebutton2.setDisable(true));
    }

    @FXML
    protected void checkStillLoggedIn() {


        if (connectivityControllerX.checkLoginStatus()) {

            loggedInIndicator.setFill(passed);
            loggedInIndicator.setOpacity(1);
        } else {
            loginUsernameBox.setText("");
            loginPasswordBox.setText("");
            loginUsernameBox.setDisable(false);
            loginPasswordBox.setDisable(false);
            loginButton.setDisable(false);
            loggedInIndicator.setFill(failed);
            loggedInIndicator.setOpacity(1);
            votebutton2.setDisable(false);
            votebutton1.setDisable(false);
        }
    }


    @FXML
    protected void login() {

        Task task = new Task<Void>() {
            @Override
            public Void call() throws Exception {
                Platform.runLater(() -> loginProgress.setVisible(true));
                Platform.runLater(() -> mainFrame.setCursor(Cursor.WAIT));
                if (http != null) {
                    http = null;
                }
                //STEP 1
                if (loginUsernameBox.getText().length() > 1 && loginPasswordBox.getText().length() > 1) {
                    checkInternetConnectivity();
                    Platform.runLater(() -> loginProgress.setProgress(0.20));
                    //STEP 2
                    checkMoltenConnecitivity();
                    Platform.runLater(() -> loginProgress.setProgress(loginProgress.getProgress() + 0.20));
                    //STEP 3
                    Platform.runLater(() -> {
                        loginUsernameBox.setDisable(true);
                        loginPasswordBox.setDisable(true);
                        loginButton.setDisable(true);

                    });

                    if (configurationService.hasConfigurationInList(ConfigurationImpl.DEFAULT_USERNAME) &&
                            configurationService.hasConfigurationInList(ConfigurationImpl.DEFAULT_PASSWORD)) {
                        Platform.runLater(() -> loginUsernameBox.setText(configurationService.getValueFromKeyInConfiguration(ConfigurationImpl.DEFAULT_USERNAME)));
                        Platform.runLater(() -> loginPasswordBox.setText(configurationService.getValueFromKeyInConfiguration(ConfigurationImpl.DEFAULT_PASSWORD)));
                    }

                    boolean result = connectivityControllerX.attemptLogin(loginUsernameBox.getText(), loginPasswordBox.getText());
                    if (result) {
                        Platform.runLater(() -> loggedInButton.setDisable(false));
                        Platform.runLater(() -> loggedInIndicator.setFill(passed));
                        Platform.runLater(() -> loggedInIndicator.setOpacity(1));

                        Platform.runLater(() -> loginProgress.setProgress(loginProgress.getProgress() + 0.20));
                        //Step 4
                        if (autovote.isSelected()) {
                            voteSite1();
                        } else {
                            boolean vote1 = connectivityControllerX.checkIfVoted(http.getConn(), 1);
                            if (!vote1) {
                                Platform.runLater(() -> votebutton1.setDisable(false));
                            }
                            Platform.runLater(() -> loginProgress.setProgress(loginProgress.getProgress() + 0.20));
                        }
                        //Step 5
                        if (autovote.isSelected()) {
                            voteSite2();
                        } else {
                            boolean vote2 = connectivityControllerX.checkIfVoted(http.getConn(), 2);
                            if (!vote2) {
                                Platform.runLater(() -> votebutton2.setDisable(false));
                            }
                            Platform.runLater(() -> loginProgress.setProgress(loginProgress.getProgress() + 0.20));
                        }

                    } else {
                        Platform.runLater(() -> {
                            loginUsernameBox.setDisable(false);
                            loginPasswordBox.setDisable(false);
                            loginButton.setDisable(false);
                        });
                        Platform.runLater(() -> loggedInIndicator.setFill(failed));
                        Platform.runLater(() -> loggedInIndicator.setOpacity(1));


                    }
                } else {
                    JOptionPane.showMessageDialog(null, "Please Enter a valid Username and Pasword!", "Login Failed!", JOptionPane.ERROR_MESSAGE);
                }
                Platform.runLater(() -> mainFrame.setCursor(Cursor.DEFAULT));
                Thread.sleep(1000);
                Platform.runLater(() -> loginProgress.setVisible(false));
                return null;
            }
        };
        Thread thx = new Thread(task);
        thx.setDaemon(true);
        new Thread(thx).start();
    }


    @FXML
    protected void checkInternetConnectivity() {
        Platform.runLater(() -> {
            try {
                if (connectivityControllerX.verifyInternetConnectivity()) {
                    checkInternetConnectivityButton.setDisable(false);
                    checkInternetConnectivityIndicator.setFill(passed);
                    checkInternetConnectivityIndicator.setOpacity(1);
                    checkMoltenConnectivityIndicator.setOpacity(1);
                    checkMoltenConnectivityButton.setDisable(false);


                } else {
                    checkInternetConnectivityIndicator.setFill(failed);
                    checkInternetConnectivityIndicator.setOpacity(1);
                    checkMoltenConnectivityButton.setDisable(false);
                }
            } catch (Exception g) {
                checkInternetConnectivityIndicator.setFill(untested);
                checkInternetConnectivityIndicator.setOpacity(0.37);
                checkMoltenConnectivityButton.setDisable(true);
            }
        });
    }

    @FXML
    protected void checkMoltenConnecitivity() {
        Platform.runLater(() -> {
            try {
                if (connectivityControllerX.verifyMoltenConnectivity()) {
                    checkMoltenConnectivityIndicator.setFill(passed);

                } else {
                    checkMoltenConnectivityIndicator.setFill(failed);
                }
            } catch (Exception g) {
                checkMoltenConnectivityIndicator.setFill(untested);
            }
        });
    }


    @FXML
    protected void delete() {

    }

    public void loadConfiguration() {
        configurationService.setup();

    }


    public void updateMenuGui() {
        // Timer??
        String autoLogin = configurationService.getValueFromKeyInConfiguration(ConfigurationImpl.SET_AUTO_LOGIN);
        if (autoLogin != null && autoLogin.equals("true")) {
            Platform.runLater(() -> loginUsernameBox.setText(configurationService.getValueFromKeyInConfiguration(ConfigurationImpl.DEFAULT_USERNAME)));
            Platform.runLater(() -> loginPasswordBox.setText(configurationService.getValueFromKeyInConfiguration(ConfigurationImpl.DEFAULT_PASSWORD)));

            Platform.runLater(() -> autologin.setSelected(true));
        } else {
            Platform.runLater(() -> autologin.setSelected(false));
        }
        String autoVote = configurationService.getValueFromKeyInConfiguration(ConfigurationImpl.SET_AUTO_VOTE);
        if (autoVote != null && autoVote.equals("true")) {
            Platform.runLater(() -> autovote.setSelected(true));
        } else {
            Platform.runLater(() -> autovote.setSelected(false));
        }
        // Update Check Box || Update Settings Indicator
        String enableConsole = configurationService.getValueFromKeyInConfiguration(ConfigurationImpl.SET_ENABLE_CONSOLE);
        if (enableConsole != null && enableConsole.equals("true")) {
            Platform.runLater(() -> console.setVisible(true));
            Platform.runLater(() -> consoleLabel.setVisible(true));
        } else {
            Platform.runLater(() -> console.setVisible(false));
            Platform.runLater(() -> consoleLabel.setVisible(false));
        }
        String minimiseToTray = configurationService.getValueFromKeyInConfiguration(ConfigurationImpl.MINIMISE_TO_TRAY_ON_STARTUP);
        if (minimiseToTray.equals("true")) {
//            autovote.setSelected(true);
        } else {
//            autovote.setSelected(false);
        }

    }

    private void updateConfigurationTimer() {
        //TODO set on timer!
        configurationService.createOrReplaceConfigurationFile();
    }

    public ConnectivityController getconnectivityControllerX() {
        return connectivityControllerX;
    }

    public void setconnectivityControllerX(ConnectivityController connectivityControllerX) {
        this.connectivityControllerX = connectivityControllerX;
    }

    public ConfigurationImpl getConfigurationService() {
        return configurationService;
    }

    public void setConfigurationService(ConfigurationImpl configurationService) {
        this.configurationService = configurationService;
    }
}
